package com.lightkits.wms.domain.pickreport;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.CommonToolsUtil;
import com.lightkits.common.MessageUtil;
import com.lightkits.common.db.entity.*;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.soa.hzero.executor.ServiceExecutor;
import com.lightkits.wms.dto.pickreport.QueryPickReportDetailRequestType;
import com.lightkits.wms.dto.pickreport.QueryPickReportDetailResponseType;
import com.lightkits.wms.dto.pickreport.models.PickReportLineDTO;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * QueryPickReportDetailExecutor
 *
 * @author zhuangwei.zheng@hand-china.com
 * Created on 2019/5/8 14:38
 */
@Component
public class QueryPickReportDetailExecutor implements ServiceExecutor<QueryPickReportDetailRequestType, QueryPickReportDetailResponseType> {
    @Override
    public QueryPickReportDetailResponseType service(QueryPickReportDetailRequestType request) {
        QueryPickReportDetailResponseType response = new QueryPickReportDetailResponseType();
        response.setSuccessful(true);
        try {
            WmRequestHeader wmRequestHeader = new WmRequestHeader()
                    .selectById(request.getWmRequestId());
            if (wmRequestHeader == null) {
                response.setSuccessful(false);
                response.setMessage(MessageFormat.format("WmRequestHeader not exist where id = {0}", request.getWmRequestId()));
                return response;
            }
            List<WmRequestLine> lineList = new WmRequestLine()
                    .selectList(new EntityWrapper<WmRequestLine>()
                            .eq(WmRequestLine.REQUEST_ID, request.getWmRequestId()));
            List<String> itemIds = new ArrayList<>();
            List<String> orgIds = new ArrayList<>();
            lineList.forEach(target -> {
                itemIds.add(target.getItemId().toString());
                orgIds.add(ObjectUtil.toString(target.getWarehouseId()));
                orgIds.add(ObjectUtil.toString(target.getWmAreaId()));
                orgIds.add(ObjectUtil.toString(target.getToWarehouseId()));
                orgIds.add(ObjectUtil.toString(target.getToWmAreaId()));
            });
            List<FndItemBase> itemBases = new ArrayList<>();
            List<FndItemTl> itemTls = new ArrayList<>();
            List<FndOrganizationTl> orgTls = new ArrayList<>();
            response.setWmRequestNumber(wmRequestHeader.getRequestNum());
            if (!itemIds.isEmpty()) {
                List<FndItemBase> items = new FndItemBase()
                        .selectList(new EntityWrapper<FndItemBase>()
                                .in(FndItemBase.ITEM_ID, itemIds));
                List<FndItemTl> tls = new FndItemTl()
                        .selectList(new EntityWrapper<FndItemTl>()
                                .in(FndItemTl.ITEM_ID, itemIds));
                itemBases.addAll(items);
                itemTls.addAll(tls);
            }
            if (!orgIds.isEmpty()) {
                List<FndOrganizationTl> tls = new FndOrganizationTl()
                        .selectList(new EntityWrapper<FndOrganizationTl>()
                                .in(FndOrganizationTl.ORGANIZATION_ID, orgIds));
                orgTls.addAll(tls);
            }
            List<PickReportLineDTO> lineDTOList = lineList
                    .stream()
                    .map(line -> new PickReportLineDTO() {
                        {
                            Optional<FndItemBase> itemBaseOpt = itemBases
                                    .stream()
                                    .filter(target -> Objects.equals(target.getItemId(), line.getItemId()))
                                    .findFirst();
                            itemBaseOpt.ifPresent(target -> {
                                setItemCode(target.getItemCode());
                                setUom(target.getPrimaryUom());
                            });

                            Optional<FndItemTl> itemTlOpt = itemTls
                                    .stream()
                                    .filter(target -> Objects.equals(target.getItemId(), line.getItemId()))
                                    .findFirst();
                            itemTlOpt.ifPresent(target -> setItemDesc(target.getDescription()));

                            Optional<FndOrganizationTl> wmAreaOpt = orgTls
                                    .stream()
                                    .filter(target -> Objects.equals(target.getOrganizationId(), line.getWmAreaId()))
                                    .findFirst();
                            wmAreaOpt.ifPresent(target -> setWmAreaName(target.getOrganizationName()));

                            Optional<FndOrganizationTl> wmWarehouseOpt = orgTls
                                    .stream()
                                    .filter(target -> Objects.equals(target.getOrganizationId(), line.getWarehouseId()))
                                    .findFirst();
                            wmWarehouseOpt.ifPresent(target -> setWarehouseName(target.getOrganizationName()));

                            Optional<FndOrganizationTl> toWmAreaOpt = orgTls
                                    .stream()
                                    .filter(target -> Objects.equals(target.getOrganizationId(), line.getToWmAreaId()))
                                    .findFirst();
                            toWmAreaOpt.ifPresent(target -> setToWmAreaName(target.getOrganizationName()));

                            Optional<FndOrganizationTl> toWarehouseOpt = orgTls
                                    .stream()
                                    .filter(target -> Objects.equals(target.getOrganizationId(), line.getToWarehouseId()))
                                    .findFirst();
                            toWarehouseOpt.ifPresent(target -> setToWarehouseName(target.getOrganizationName()));
                            setApplyQty(ObjectUtil.toString(line.getApplyQty()));
                            setCompleteQty(ObjectUtil.toString(line.getExeutedQty()));
                            setLineId(line.getId().toString());
                            setWarehouseId(ObjectUtil.toString(line.getWarehouseId()));
                            setToWarehouseId(ObjectUtil.toString(line.getToWarehouseId()));
                            setWmAreaId(ObjectUtil.toString(line.getWmAreaId()));
                            setToWmAreaId(ObjectUtil.toString(line.getToWmAreaId()));
                        }
                    }).collect(Collectors.toList());
            FndOrganizationTl orgTl = new FndOrganizationTl()
                    .selectOne(new EntityWrapper<FndOrganizationTl>()
                            .eq(FndOrganizationTl.ORGANIZATION_ID, wmRequestHeader.getOrganizationId()));
            FndResourceTl prodLineTl = new FndResourceTl()
                    .selectOne(new EntityWrapper<FndResourceTl>()
                            .eq(FndResourceTl.RESOURCE_ID, wmRequestHeader.getProdLineId()));
            BdMoBase moBase = new BdMoBase().selectById(wmRequestHeader.getMoId());
            if (orgTl != null) {
                response.setOrgName(orgTl.getOrganizationName());
            }
            if (prodLineTl != null) {
                response.setProdLineName(prodLineTl.getResourceName());
            }
            if (moBase != null) {
                response.setMoNumber(moBase.getMoNum());
            }
            response.setTypeMeaning(MessageUtil
                    .getSysCodeMeaning("WM_REQUEST_TYPE", wmRequestHeader.getRequestType()));
            response.setStatusMeaning(MessageUtil
                    .getSysCodeMeaning("WM_REQUEST_STATUS", wmRequestHeader.getProcessStatus()));
            response.setWmRequestId(wmRequestHeader.getId().toString());
            response.setLineDTOS(lineDTOList);
        } catch (Exception e) {
            CommonToolsUtil.executeException(e, response);
        }
        return response;
    }
}
